/*****************************************************************************
* University of Southern Denmark
* Embedded Programming (EMP)
*
* MODULENAME.: uart.c
*
* PROJECT....: Assignment 7
*
* DESCRIPTION: See module specification file (.h-file).
*
* Change Log:
******************************************************************************
* Date    Id    Change
* YYMMDD
* --------------------
* 120406  AP    Module created.
*
*****************************************************************************/

/***************************** Include files *******************************/
#include "uart.h"
#include "FreeRTOS.h"
#include "Task.h"
#include "inc\lm3s6965.h"
#include "..\inc\ecp_type.h"
#include "lcd\lcd.h"
#include "watch\watch.h"
/*****************************    Defines    *******************************/
#define BAUDRATE 19200
#define SET_CLOCK 20
#define GET_CLOCK 22
/*****************************   Constants   *******************************/

/*****************************   Variables   *******************************/
double BRD; // used in baud rate equation
int IBRD, FBRD, wait; // integer and fractional part of baudrate
/*****************************   Functions   *******************************/

void init_UART(void)
/*****************************************************************************
*   Input    :
*   Output   :
*   Function : Initialize UART settings
******************************************************************************/
{
	taskENTER_CRITICAL(); // Enter critical section! (disable interrupts)
	// Initialize Clock
	SYSCTL_RCGC1_R |= SYSCTL_RCGC1_UART0;

    // Initialize GPIOA clock
    SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA;

	// Delay to wait for clocks
	wait = SYSCTL_RCGC1_R;

    // Enable GPIO pins 0 and 1 for hardware operation (UART0)
    GPIO_PORTA_DEN_R |= 0x3;
    GPIO_PORTA_AFSEL_R |= 0x3;

	// Configure Baudrate
	BRD = configCPU_CLOCK_HZ /(16 * BAUDRATE);

	IBRD = (int)BRD; // cast as integer to remove fractional part.
	FBRD = (int)(((BRD - IBRD) * 64.0) + 0.5); // calculate fractional part, 0.5 is added to account for rounding error.

	// Disable UART, to be able to change control registers.
	UART0_CTL_R &= ~(UART_CTL_UARTEN);

	// Write integer part of BRD to the UARTIBRD register
	UART0_IBRD_R = IBRD;

	// Write fractional part of BRD to the UARTFBRD register
	UART0_FBRD_R = FBRD;

	// Baudrate configured

	//Line control register can now be written, must be done after Baudrate.
	//One stopbit, no partity check, 8 bit words and fifo's enabled. one stop and no parity is default settings.
	UART0_LCRH_R |= UART_LCRH_WLEN_8; // set wordlength to 8 bit
	UART0_LCRH_R |= UART_LCRH_FEN;	// enable fifo buffers

	// interrupt setting, sat at maximum, so it's likely never to interrupt, and as such we don't need to handle interrupts. :)
	UART0_IFLS_R |= UART_IFLS_RX7_8; 	// recive interrupt at 7/8 full
	UART0_IFLS_R |= UART_IFLS_TX7_8;	// transmit interrupt at 7/8 ful

	// Enable UART
	UART0_CTL_R |= UART_CTL_TXE;		// enable transmit
	UART0_CTL_R |= UART_CTL_RXE;		// enable receive
	UART0_CTL_R |= UART_CTL_UARTEN;		// enable UART, transmit and receive enabled by default.

	taskEXIT_CRITICAL(); // Exit critical section!
}

void send_task(void* pvParameters)
/*****************************************************************************
*   Input    :
*   Output   :
*   Function : send_task, this task sends data from the UART.
******************************************************************************/
{
	while(1)
	{
			// Send any items waiting in send_buffer
			if (uxQueueMessagesWaiting(send_buffer) > 0 &&
					!(UART0_FR_R & UART_FR_TXFF))
			{
					xSemaphoreTake(send_buffer_mutex, portMAX_DELAY);
					INT8U charToSend;
					xQueueReceive(send_buffer, &charToSend, 0);
					UART0_DR_R = charToSend & UART_DR_DATA_M; // write to UART_data
					xSemaphoreGive(send_buffer_mutex);
			}

			vTaskDelay(5); // Delay for other tasks to run
	}
}

void receive_task(void* pvParameters)
/*****************************************************************************
*   Input    :
*   Output   :
*   Function : receive_task, this task receives data from the UART.
******************************************************************************/
{
	while(1)
	{
			// Receive any items waiting in receive FIFO
			if (!(UART0_FR_R & UART_FR_RXFE))
			{
					xSemaphoreTake(read_buffer_mutex, portMAX_DELAY);
					INT8U receivedChar = (UART0_DR_R & UART_DR_DATA_M); // read from UART_data
					xQueueSendToBack(read_buffer, &receivedChar, 0);
					xSemaphoreGive(read_buffer_mutex);
			}

			vTaskDelay(5); // Delay for other tasks to run
	}
}

/****************************** End Of Module *******************************/
